package main

import (
	"context"
	"fmt"
	"time"
)

func main() {

	// 在主线程中定义一个 baseCtx 并向其中写入数据
	baseCtx := context.Background()
	// 向 baseCtx 中写入数据后会生成一个新上下文 ctx
	ctx := context.WithValue(baseCtx, "a", "b")

	// 将 baseCtx 传入协程，协程中会从 baseCtx 中读取数据
	go func(c context.Context) {
		fmt.Println(c.Value("a"))
	}(ctx)

	// 基于 baseCtx 创建一个带 timeout 的 timeoutCtx
	timeoutCtx, cancel := context.WithTimeout(baseCtx, time.Second)
	// timeoutCtx 在到时间后一定会被 cancel 掉
	defer cancel()

	// 将 timeoutCtx 传入协程
	go func(timeoutCtxP context.Context) {

		// 定义一个定时器 ticker，时钟频率 1s
		ticker := time.NewTicker(1 * time.Second)

		// for 循环的执行频率基于定时器 ticker 的设置
		for _ = range ticker.C {
			select {
				// defer 会保证 timeoutCtxP 会被 cancel 掉，cancel 掉就会进入这段逻辑
				case <-timeoutCtxP.Done():
					fmt.Println("child process interrupt...")
					return
				default:
					fmt.Println("enter default")
			}
		}
	}(timeoutCtx)

	select {
		// 主线程中也会监听 timeoutCtx 的 cancel 事件，监听到后退出
		case <-timeoutCtx.Done():
			time.Sleep(1 * time.Second)
			fmt.Println("main process exit!")
	}
}
